package chen.web.user;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import chen.web.cache.CacheUtils;

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
import net.sf.ehcache.config.CacheConfiguration;
import net.sf.ehcache.store.MemoryStoreEvictionPolicy;

public class CachedAccountManager implements AccountManager{

	private static final String AccountCacheName = "AccountCache";
	private static final String TotalAccountCacheName = "TotalAccount";
	private static final String TotalAccountCacheKey = "TotalAccountCacheKey";
	private static Cache AccountCache = null;
	private static Cache TotalAccountCache = null;
	private AccountManager am;
	public CachedAccountManager(AccountManager am){
		this.am = am;
		AccountCache = CacheManager.getInstance().getCache(AccountCacheName);
		
		CacheConfiguration config = new CacheConfiguration(TotalAccountCacheName, 1)
									.memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.FIFO)
									.eternal(false)
									.diskPersistent(false)
									.timeToLiveSeconds(24 * 3600);
		TotalAccountCache = new Cache(config);
		CacheManager.create().addCache(TotalAccountCache);
		
		CacheUtils.storeDescription(TotalAccountCache, "用于缓存账号总数");
		CacheUtils.storeDescription(AccountCache, "用于缓存账号");
	}
	
	private Account putInCache(Account account){
		account.clean();
		Element element = new Element(account.getId(), account);
		AccountCache.put(element);
		return account;
	}
	
	private Account getFromCache(int id){
		Element element = AccountCache.get(id);
		if(element != null){
			Account acc = (Account)element.getValue();
			if(acc.isDirty()){
				AccountCache.remove(id);
			} else {
				return acc;
			}
		}
		return null;
	}
	
	private void increaseTotalAccount(int increase){
		Element elem = TotalAccountCache.get(TotalAccountCacheKey);
		if(elem != null){
			int total = (Integer)elem.getValue();
			Element newElem = new Element(TotalAccountCacheKey, total + increase);
			TotalAccountCache.put(newElem);
		}
	}

	@Override
	public Account changeEmail(Account account, String newEmail)
			throws EmailAlreadyBeenRegisteredException {
		// TODO Auto-generated method stub
		return putInCache(am.changeEmail(account, newEmail));
	}

	@Override
	public Account changeEmail(String email, String password)
			throws InvalidPasswordException,
			EmailAlreadyBeenRegisteredException {
		// TODO Auto-generated method stub
		return putInCache(am.changeEmail(email, password));
	}

	@Override
	public Account changePassword(String newPassword, String oldPassword)
			throws InvalidPasswordException {
		// TODO Auto-generated method stub
		return putInCache(am.changePassword(newPassword, oldPassword));
	}

	@Override
	public Account changePassword(Account account, String newPassword) {
		// TODO Auto-generated method stub
		return putInCache(am.changePassword(account, newPassword));
	}

	@Override
	public Account changeRole(Account account, Role role) {
		// TODO Auto-generated method stub
		return putInCache(am.changeRole(account, role));
	}

	@Override
	public void deleteAccount(Account account) {
		// TODO Auto-generated method stub
		am.deleteAccount(account);
		AccountCache.remove(account.getId());
		increaseTotalAccount(-1);
	}

	@Override
	public Account getAccount(int id) {
		// TODO Auto-generated method stub
		Account acc = getFromCache(id);
		if(acc != null){
			return acc;
		}
		return putInCache(am.getAccount(id));
	}

	@Override
	public List<Account> getAccount(List<Integer> ids) {
		// TODO Auto-generated method stub
		//存放没有缓存的帐号id
		List<Integer> idList = new ArrayList<Integer>();
		Map<Integer, Account> temp = new HashMap<Integer, Account>();
		for(int id : ids){
			Account acc = getFromCache(id);
			if(acc != null){
				temp.put(acc.getId(), acc);
			} else {
				idList.add(id);
			}
		}
		//获取没有缓存的数据
		if(idList.size() > 0){
			List<Account> accList = am.getAccount(idList);
			for(Account acc : accList){
				putInCache(acc);
				temp.put(acc.getId(), acc);
			}
			
		}
		
		//保证数据大小和顺序一致
		List<Account> result = new ArrayList<Account>(ids.size());
		for(int i=0; i<ids.size(); i++){
			int id = ids.get(i);
			Account acc = temp.get(id);
			result.add(acc);
		}
		return result;
	}

	@Override
	public Account getAccountByEmail(String email) {
		// TODO Auto-generated method stub
		return am.getAccountByEmail(email);
	}

	@Override
	public Account getAccountByName(String nickname) {
		// TODO Auto-generated method stub
		return am.getAccountByName(nickname);
	}

	@Override
	public Account increaseRank(Account account, int increase) {
		// TODO Auto-generated method stub
		return putInCache(am.increaseRank(account, increase));
	}

	@Override
	public void mergeAccount(Role oldRole, Role newRole) {
		// TODO Auto-generated method stub
		AccountCache.removeAll();
		am.mergeAccount(oldRole, newRole);
	}

	@Override
	public Account register(String nickname, String password, String email)
			throws NicknameAlreadyBeenRegisteredException,
			EmailAlreadyBeenRegisteredException {
		// TODO Auto-generated method stub
		Account acc = am.register(nickname, password, email);
		increaseTotalAccount(1);
		return putInCache(acc);
	}

	@Override
	public int totalAccount() {
		// TODO Auto-generated method stub
		Element elem = TotalAccountCache.get(TotalAccountCacheKey);
		if(elem == null){
			int total = am.totalAccount();
			elem = new Element(TotalAccountCacheKey, total);
			TotalAccountCache.put(elem);	
			return total;
		} else {
			return (Integer)elem.getValue();
		}
	}

	@Override
	public void update(Account account) {
		// TODO Auto-generated method stub
		am.update(account);
		putInCache(account);
	}
}
